package net.butfly.bus.hessian.invoker;

import java.net.MalformedURLException;
import java.util.List;

import net.butfly.albacore.exception.SystemException;
import net.butfly.bus.Constants;
import net.butfly.bus.Request;
import net.butfly.bus.Response;
import net.butfly.bus.hessian.config.invoker.HessianInvokerConfig;
import net.butfly.bus.invoker.Invoker;
import net.butfly.bus.invoker.InvokerBase;
import net.butfly.bus.server.EntryPoint;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.caucho.hessian.client.HessianConnectionException;
import com.caucho.hessian.client.HessianProxyFactory;
import com.caucho.hessian.client.HessianRuntimeException;
import com.caucho.hessian.io.AbstractSerializerFactory;

public class HessianInvoker extends InvokerBase<HessianInvokerConfig> implements Invoker<HessianInvokerConfig> {
	private static Logger logger = LoggerFactory.getLogger(HessianInvoker.class);
	private static long DEFAULT_TIMEOUT = 5000;
	private String path;
	private long timeout;
	private List<Class<? extends AbstractSerializerFactory>> translators;

	@Override
	public void initialize(HessianInvokerConfig config) {
		this.path = config.getPath();
		this.timeout = config.getTimeout() > 0 ? config.getTimeout() : DEFAULT_TIMEOUT;
		this.translators = config.getTypeTranslators();
		super.initialize(config);
	}

	@Override
	public void invoke(Response response, Request request) {
		try {
			HessianProxyFactory factory = new HessianProxyFactory();

			AbstractSerializerFactory af = null;
			for (Class<? extends AbstractSerializerFactory> clazz : this.translators) {
				try {
					af = clazz.newInstance();
				} catch (Exception ex) {}
				factory.getSerializerFactory().addFactory(af);
			}
			factory.setConnectTimeout(timeout);

			EntryPoint proxy = (EntryPoint) factory.create(EntryPoint.class, path);
			logger.info("Attemp hessian connection: " + path + ".");
			response.copyFrom(proxy.invoke(request));
		} catch (MalformedURLException ex) {
			throw new SystemException(Constants.SystemError.HESSIAN_CONNECTION, "Hessian url [" + path + "] invalid.", ex);
		} catch (HessianConnectionException ex) {// 连接异常
			throw new SystemException(Constants.SystemError.HESSIAN_CONNECTION, "Hessian connection [" + path + "] invalid.",
					ex);
		} catch (HessianRuntimeException ex) {
			throw new SystemException(Constants.SystemError.HESSIAN_CONNECTION, "Hessian service [" + path + "] invalid.",
					ex.getCause());
		}
	}
}
